<template>
  <div class="container">
    <!--  头部内容-->
    <div class="header">
      <div class="logo_title">华润江中GAP中药材基地一体化展示大屏</div>
      <div class="nav">
        <div class="item active">首页</div>
        <div class="item">江中药业</div>
        <div class="item">济生药业</div>
        <div class="item">江中饮片</div>
      </div>
    </div>

    <!--  左边布局-->
    <div class="left">
      <div class="section">
        <div class="title">种植面积排名数据</div>
        <div class="content">
          <div class="echarts_subtitle">单位：亩</div>
          <div ref="echartsLeft1" id="echarts-left-1" style="width:100%;height: 95%;"></div>
        </div>
      </div>

      <div class="section">
        <div class="title">各地区种植品种分布数量统计</div>
        <div class="content">
          <div ref="echartsLeft2" id="echarts-left-2" style="width:100%;height: 95%;"></div>
        </div>
      </div>

      <div class="section">
        <div class="title">各地区基地面积排行数据统计</div>
        <div class="content">
          <div ref="echartsLeft3" id="echarts-left-3" style="width:100%;height: 95%;"></div>
        </div>
      </div>

    </div>

    <!--  右边布局-->
    <div class="right">
      <div class="section">
        <div class="title">基地推广面积及农户数量</div>
        <div class="content">
          <div ref="echartsLeft4" id="echarts-left-4" style="width:100%;height: 95%;"></div>
        </div>
      </div>
      <div class="section">
        <div class="title">溯源信息监管</div>
        <div class="content1">
          <div class="list1">
            <div class="item tab">
              <p>品名</p>
              <p>批次</p>
              <p>状态</p>
              <p>&nbsp;</p>
            </div>
            <vue-seamless-scroll :data="listData" class="list1Warp" :class-option="optionHover">
              <div class="item" v-for="(item, index) in listData" :key="index">
                <p>浙贝母</p>
                <p>20240501</p>
                <p>已发码</p>
                <p><img src="@/assets/images/index/code.png"></p>
              </div>
            </vue-seamless-scroll>
          </div>
        </div>
      </div>

      <div class="section">
        <div class="title">推广基地中农户地块扫码次数</div>
        <div class="content2">
          <div class="list">
            <vue-seamless-scroll :data="listData" class="list1Warp" :class-option="optionHover">
              <div class="item" v-for="(item, index) in listData" :key="index">
                <div class="info">
                  <div class="sleft">
                    <p class="num">
                      <img src="@/assets/images/index/top1.png" v-if="index == 0">
                      <img src="@/assets/images/index/top2.png" v-else-if="index == 1">
                      <img src="@/assets/images/index/top3.png" v-else-if="index == 2">
                      <span v-else>{{ index + 1 }}</span>
                    </p>
                    <p class="name">太子参推广基地</p>
                  </div>
                  <div class="sright">5000次</div>
                </div>
                <div class="porgressBox">
                  <div class="progressPer"></div>
                  <div class="progressAct"></div>
                </div>
              </div>
            </vue-seamless-scroll>
          </div>
        </div>
      </div>
    </div>

    <!-- <div class="tipsLabel">
      <div class="item">
        <img src="@/assets/images/index/cicle1.svg">
        种植基地
      </div>
      <div class="item">
        <img src="@/assets/images/index/cicle2.svg">
        GAP基地
      </div>
    </div> -->

    <!--地图返回-->
    <div class="returns" @click="returns" v-show="mapStatus != '国'">返回</div>

    <!--  中间汇总数据 -->
    <div class="statistics">
      <div class="item">
        <div class="thumb"><img src="@/assets/images/index/icon1.png"></div>
        <div class="info">
          <p class="name">药材品种数量</p>
          <p class="num">
            <CountTo :startVal='0' :endVal='1726' :duration='1500' /><span class="unit">种</span>
          </p>
        </div>
        <div class="divide">
          <img src="@/assets/images/index/divide.png">
        </div>
      </div>
      <div class="item">
        <div class="thumb"><img src="@/assets/images/index/icon2.png"></div>
        <div class="info">
          <p class="name">基地数量</p>
          <p class="num">
            <CountTo :startVal='0' :endVal='1726' :duration='1500' /><span class="unit">个</span>
          </p>
        </div>
        <div class="divide">
          <img src="@/assets/images/index/divide.png">
        </div>
      </div>
      <div class="item">
        <div class="thumb"><img src="@/assets/images/index/icon3.png"></div>
        <div class="info">
          <p class="name">GAP基地</p>
          <p class="num">
            <CountTo :startVal='0' :endVal='1726' :duration='1500' /><span class="unit">个</span>
          </p>
        </div>
        <div class="divide">
          <img src="@/assets/images/index/divide.png">
        </div>
      </div>
      <div class="item">
        <div class="thumb"><img src="@/assets/images/index/icon4.png"></div>
        <div class="info">
          <p class="name">基地面积</p>
          <p class="num">
            <CountTo :startVal='0' :endVal='1726' :duration='1500' /><span class="unit">亩</span>
          </p>
        </div>
        <div class="divide">
          <img src="@/assets/images/index/divide.png">
        </div>
      </div>
      <div class="item">
        <div class="thumb"><img src="@/assets/images/index/icon5.png"></div>
        <div class="info">
          <p class="name">推广基地面积</p>
          <p class="num">
            <CountTo :startVal='0' :endVal='1726' :duration='1500' /><span class="unit">亩</span>
          </p>
        </div>
        <div class="divide">
          <img src="@/assets/images/index/divide.png">
        </div>
      </div>
      <div class="item">
        <div class="thumb"><img src="@/assets/images/index/icon6.png"></div>
        <div class="info">
          <p class="name">带动农户数量</p>
          <p class="num">
            <CountTo :startVal='0' :endVal='1726' :duration='1500' /><span class="unit">户</span>
          </p>
        </div>
        <!-- <div class="divide">
          <img src="@/assets/images/index/divide.png">
        </div> -->
      </div>

    </div>

    <!--  视频布局 -->
    <div class="videoBox">
      <div class="title">
        <span>江中宣传视频</span>
        <!-- 采用分页模式 -->
        <div class="tab">
          <div class="tabItem"><i class="el-icon-arrow-left"></i></div>
          <div class="tabItem"><i class="el-icon-arrow-right"></i></div>
        </div>
      </div>
      <div class="content">
        <div class="item" @click="openVideo()">
          <span>基地名称</span>
          <img src="@/assets/images/index/image1.png">
          <img src="@/assets/images/index/play.svg" class="svg">
        </div>
        <div class="item" @click="openVideo()">
          <span>基地名称</span>
          <img src="@/assets/images/index/image2.png">
          <img src="@/assets/images/index/play.svg" class="svg">
        </div>
        <div class="item" @click="openVideo()">
          <span>基地名称</span>
          <img src="@/assets/images/index/image3.png">
          <img src="@/assets/images/index/play.svg" class="svg">
        </div>
      </div>
    </div>

    <div class="bottom">
      <img src="@/assets/images/index/footer.png" />
    </div>

    <!--  三维地图 -->
    <div class="main" ref="threejs"></div>

    <div class="layerInfo" v-if="map.showLayer"
      :style="{ 'left': (map.left - 122) + 'px', 'top': (map.right - 300) + 'px' }">
      <div class="list">
        <div class="item" v-for="(item, index) in 5">
          <div class="content">
            <div class="title">太子参种植GAP基地</div>
            <div class="des">种植品种：太子参</div>
            <div class="des">种植面积：300亩</div>
          </div>
          <div class="more">
            <img src="@/assets/images/index/more.png">
          </div>
        </div>
      </div>
    </div>

    <!--  视频弹窗 -->
    <div class="layerBox" v-if="showVideo">
      <div class="showlayer">
        <div class="title">
          <div class="info">
            <img src="@/assets/images/index/video.svg">
            <span>太子参基地</span>
          </div>
          <div class="closed" @click="closeVideo()">
            <img src="@/assets/images/index/closed.png">
          </div>
        </div>
        <div class="content">
          <div id="dplayer"></div>
        </div>
      </div>
    </div>

    <!-- 右侧按钮 -->
    <div class="rightButton" ref="rightButton">
      <div v-for="(item, index) in rightButItem" :key="index" :value="item.value"
        :class="item.selected ? 'selected common' : 'common'" @click="rightButClick">
        {{ item.name }}
      </div>
    </div>

    <!-- 省份名称元素 -->
    <div id="provinceName" style="display: none"></div>
    <!-- 城市名称元素 -->
    <div id="cityName" style="display: none"></div>
    <!-- 棱柱上方数值元素 -->
    <div id="prismValue" style="display: none"></div>
    <!-- 地图标牌元素 -->
    <div id="mapTag" style="display: none">
      <div class="content">
        <div>旅客:</div>
        <div id="mapTag_value">1024万</div>
      </div>
      <div class="arrow"></div>
    </div>
    <!-- 地图弹窗 弹框元素 -->
    <div id="popup" style="display: none">
      <div class="popup_line"></div>
      <div class="popup_Main">
        <div class="popupMain_top"></div>
        <div class="popup_content">
          <div class="popup_head">
            <div class="popup_title">
              <div class="title_icon"></div>
              <div id="popup_Name">湖北省</div>
            </div>
            <div class="close" @click="popupClose"></div>
          </div>
          <div class="popup_item">
            <div>当前流入：</div>
            <div class="item_value">388万人次</div>
          </div>
          <div class="popup_item">
            <div>景区容量：</div>
            <div class="item_value">2688万人次</div>
          </div>
          <div class="popup_item">
            <div>交通资源利用率：</div>
            <div class="item_value">88.7%</div>
          </div>
          <div class="popup_item">
            <div>省市热搜指数：</div>
            <div class="item_value">88.7%</div>
          </div>
        </div>
        <div class="popupMain_footer"></div>
      </div>
    </div>
  </div>
</template>

<script>
import request from "@/utils/request";
import mqtt from 'mqtt';
import DPlayer from 'dplayer';
import CountTo from 'vue-count-to';
import * as echarts from "echarts";
import "echarts-gl";  // 必须引入 echarts-gl 库‌:ml-citation{ref="1" data="citationList"}
import * as THREE from "three";
import TWEEN from "@tweenjs/tween.js";
import { CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer.js";
import { CSS3DObject } from "three/examples/jsm/renderers/CSS3DRenderer.js";
// threejs基础配置，场景相机渲染器等
import { scene, camera, controls, renderer, css3DRenderer, css2DRenderer, outlinePass, composer, finalComposer, mirror } from "@/utils/three/baseConfig/index.js";
// 加载地图
import { loadChinaMapData, mapModel, cityData, mapUf, projection, waterObj } from "@/utils/three/initChinaMap/index.js";
// 地图底部网格背景
import { gridHelper, meshPoint } from "@/utils/three/backgroundMesh/index.js";
// 初始化鼠标移入地图浮动效果
import { initMapFloat } from "@/utils/three/mapFloat/index.js";
// 地图圆圈背景
import { circleUf, outerCircle, innerCircle, diffuseCircle, gradientPlane, planeUf } from "@/utils/three/backgroundCircle/index.js";
// 飞线组对象，更新飞线函数，飞线动画
import { flyGroup, updateFlyLine, flyLineAnimation } from "@/utils/three/flyLine/index.js";
// 棱柱组对象，创建棱柱函数
import { prismGroup, createPrismn, prismGlowArr } from "@/utils/three/prism/index.js";
import { createProvinceName, apertureArr } from "@/utils/three/provinceName/index.js";
import { createMapTag, tagGroup } from "@/utils/three/mapTag/index.js";
import { particlesUpdate, createParticles, particles } from "@/utils/three/particles/index.js";
import vueSeamlessScroll from 'vue-seamless-scroll'

export default {
  components: {
    CountTo,
    vueSeamlessScroll
  },
  data() {
    return {
      map: {
        showLayer: false,
        left: 0,
        right: 0,
      },
      config: {
        username: "admin",
        password: "btg123456.",
      },
      showDataNum: 10,
      listData: [{
        'title': '无缝滚动第一行无缝滚动第一行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第二行无缝滚动第二行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第三行无缝滚动第三行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第四行无缝滚动第四行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第五行无缝滚动第五行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第六行无缝滚动第六行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第七行无缝滚动第七行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第八行无缝滚动第八行',
        'date': '2017-12-16'
      }, {
        'title': '无缝滚动第九行无缝滚动第九行',
        'date': '2017-12-16'
      }],
      showVideo: false,
      isGj: false,
      dialogShow: false,
      isVisible: true,
      singleObject: {},
      cjlist: [],
      gjlist: [],
      ecgLevel: {},
      healthLevel: {},
      diagLevel: {},
      client: null,
      // 右侧按钮选项
      rightButItem: [
        { value: "tourism", name: "刷色图", selected: false },
        { value: "prism", name: "棱柱", selected: false },
        { value: "flyLine", name: "飞线", selected: false },
        { value: "ripple", name: "波纹", selected: true },
        { value: "tag", name: "标牌", selected: false },
        { value: "particles", name: "粒子", selected: false },
        { value: "mirror", name: "倒影", selected: true },
      ],
      mapStatus: '国', // 初始值
      // 非响应式数据（需在 created 中初始化）
      clock: null,
      glowModel: null,
      rayObj: null,
      divTag: null,
      css2Dpopup: null,
      glowArr: [],
      size: null,
      provinceSize: null,
      provinceModel: null/* 省模型数据 */,
      cityModel: null/* 市模型数据 */
    }
  },
  computed: {
    currentShowModel() {
      if (this.mapStatus === '国') {
        return mapModel;
      } else if (this.mapStatus === '省') {
        return this.provinceModel;
      } else {
        return this.cityModel;
      }
    },
    optionHover() {
      return {
        step: 0.3, // 数值越大速度滚动越快
        limitMoveNum: 1, // 开始无缝滚动的数据量 this.dataList.length
        hoverStop: true, // 是否开启鼠标悬停stop
        direction: 1, // 0向下 1向上 2向左 3向右
        openWatch: true, // 开启数据实时监控刷新dom
        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
        waitTime: 1000, // 单步运动停止的时间(默认值1000ms)
      };
    },
  },
  created() {
    // 初始化 Three.js 相关对象
    this.clock = new THREE.Clock();
    this.provinceModel = new THREE.Group();
    this.provinceModel.name = "省";
    this.provinceModel.rotateX(-Math.PI / 2);
    this.provinceModel.visible = false;

    this.cityModel = new THREE.Group();
    this.cityModel.name = "市";
    this.cityModel.rotateX(-Math.PI / 2);
    this.cityModel.visible = false;
    this.divTag = document.getElementById("popup");
  },
  mounted() {
    // 添加窗口大小改变的事件监听器
    window.addEventListener('resize', this.handleResize);
    this.initThree();
    // if(document.documentElement.clientHeight < 1106 && document.documentElement.clientHeight > 1080){
    //   this.showDataNum = 5
    // }else if(document.documentElement.clientHeight > 1106){
    //   this.showDataNum = 6
    // } else if(document.documentElement.clientHeight < 1080){
    //   this.showDataNum = 4
    // }
    this.initChart1();
    this.initChart2();
    this.initChart3();
    this.initChart4();
    // 初始化 DOM 引用
    // this.rightButton = this.$refs.rightButton;

    // this.getlist();
    // this.getlist1();
    // // this.mqttSocket();
    // this.testmqttSocket();
    // this.getDict('ecg_level');
    // this.getDict('health_level');
    // this.getDict('diag_labels');
  },
  beforeDestroy() {
    // 清理 Three.js 资源
    if (this.provinceModel) this.provinceModel.dispose();
    if (this.cityModel) this.cityModel.dispose();
    // 移除窗口大小改变的事件监听器，以避免内存泄漏
    window.removeEventListener('resize', this.handleResize);
  },
  methods: {
    handleResize() {
      location.reload();
    },
    async initThree() {
      this.threejs = this.$refs.threejs;
      this.threejs.appendChild(renderer.domElement);
      this.threejs.appendChild(css3DRenderer.domElement);
      this.threejs.appendChild(css2DRenderer.domElement);
      scene.add(this.provinceModel, this.cityModel);

      // 创建省份名称对象
      createProvinceName();
      // 创建粒子
      createParticles();
      // 加载中国地图
      await loadChinaMapData();
      const box = new THREE.Box3().setFromObject(mapModel);
      // 计算模型的长宽
      const length = box.max.x - box.min.x;
      const width = box.max.z - box.min.z;
      this.size = (length + width) / 2;
      console.log(this.size, "size");
      // 初始化鼠标移入地图浮动效果
      initMapFloat(camera, mapModel, this.provinceModel, this.cityModel);
      // 初始化地图点击发光效果
      this.initMapClickGlow();
      // 初始化地图双击切换省份效果
      this.initMapDoubleClick();
      // 创建棱柱
      // createPrismn(cityData, waterObj);
      // 创建地图标牌
      // createMapTag(cityData, waterObj);
      // scene.add(mapModel, gridHelper, meshPoint, outerCircle, innerCircle, diffuseCircle, gradientPlane, tagGroup);
      scene.add(mapModel, tagGroup);
      // 设置需要辉光物体数组
      this.glowArr = [...prismGlowArr, flyGroup.children];
      // 开始循环渲染
      this.render();
      // 首次进入动画
      this.eventAnimation();
    },
    initChart1() {
      const myChart = echarts.init(this.$refs.echartsLeft1); //初始化容器
      var ydata = ['黄芪', '栀子', '浙贝母', '元胡', '铁皮石斛'];
      var salvProValue = [135, 144, 154, 181, 239];
      const option = {
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "shadow",
          },
        },
        grid: {
          left: '2%',
          right: '4%',
          bottom: '2%',
          top: '5%',
          containLabel: true,
        },
        yAxis: {
          type: 'value',
          splitLine: {
            show: true,
            lineStyle: {
              type: 'dashed',
              color: 'rgba(8, 116, 229, 0.3)'
            }
          },
          axisLabel: {
            color: "rgba(255, 255, 255, 0.8)",
            show: true
          },
        },
        xAxis: {
          type: "category",
          data: ydata,
          axisLine: {
            show: true,
          },
          axisTick: {
            show: true,
          },
          axisLabel: {
            color: "rgba(255, 255, 255, 0.8)",
            show: true
          },
        },
        series: [
          {
            type: 'bar',
            zlevel: 1,
            showBackground: false,
            barWidth: 20,
            data: salvProValue,
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: '#0783FA' // 起始颜色（不透明）
                },
                {
                  offset: 1,
                  color: 'rgba(7, 131, 250, 0)' // 结束颜色（完全透明）
                }
              ])
            }
          }
        ],
      };

      myChart.setOption(option);
    },
    initChart2() {
      const myChart = echarts.init(this.$refs.echartsLeft2); //初始化容器
      // 选中索引
      let hoveredIndex = '';
      /** 颜色组 */
      let colors = ['#FFD15C', '#07D1FA', '#0783FA', '#0AA974']

      //设置扇形高度  0：为自定义高度
      const itemHeight = 20
      // 扇形数据
      const optionsData = [
        {
          name: '安徽省',
          value: 60,
          num: 4,
          type: '黄芪、栀子、 浙贝母、元胡',
        },
        {
          name: '贵州省',
          value: 44,
          num: 3,
          type: '黄芪、栀子、 浙贝母',
        },
        {
          name: '江西省',
          value: 32,
          num: 2,
          type: '黄芪、栀子',
        },
        {
          name: '四川省',
          value: 32,
          num: 1,
          type: '黄芪',
        },
      ]

      // 生成扇形的曲面参数方程
      function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
        // 计算
        const midRatio = (startRatio + endRatio) / 2;

        const startRadian = startRatio * Math.PI * 2;
        const endRadian = endRatio * Math.PI * 2;
        const midRadian = midRatio * Math.PI * 2;

        // 如果只有一个扇形，则不实现选中效果。
        if (startRatio === 0 && endRatio === 1) {
          // eslint-disable-next-line no-param-reassign
          isSelected = false;
        }

        // 通过扇形内径/外径的值，换算出辅助参数 k（默认值 1/3）
        // eslint-disable-next-line no-param-reassign
        k = typeof k !== 'undefined' ? k : 1 / 3;

        // 计算选中效果分别在 x 轴、y 轴方向上的位移（未选中，则位移均为 0）
        const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
        const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;

        // 计算高亮效果的放大比例（未高亮，则比例为 1）
        const hoverRate = isHovered ? 1.05 : 1;

        // 返回曲面参数方程
        return {
          u: {
            min: -Math.PI,
            max: Math.PI * 3,
            step: Math.PI / 32,
          },

          v: {
            min: 0,
            max: Math.PI * 2,
            step: Math.PI / 20,
          },

          x(u, v) {
            if (u < startRadian) {
              return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
            }
            if (u > endRadian) {
              return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
            }
            return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
          },

          y(u, v) {
            if (u < startRadian) {
              return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
            }
            if (u > endRadian) {
              return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
            }
            return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
          },

          z(u, v) {
            if (u < -Math.PI * 0.5) {
              return Math.sin(u);
            }
            if (u > Math.PI * 2.5) {
              return Math.sin(u) * h * 0.1;
            }
            // 当前图形的高度是Z根据h（每个value的值决定的）
            return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
          },
        };
      }
      // 监听 mouseover，近似实现高亮（放大）效果
      myChart.on('mouseover', function (params) {
        // 准备重新渲染扇形所需的参数
        let isSelected;
        let isHovered;
        let startRatio;
        let endRatio;
        let k;
        let i;

        // 如果触发 mouseover 的扇形当前已高亮，则不做操作
        if (hoveredIndex === params.seriesIndex) {
          return;
          // 否则进行高亮及必要的取消高亮操作
        } else {
          // 如果当前有高亮的扇形，取消其高亮状态（对 option 更新）
          if (hoveredIndex !== '') {
            // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 false。
            isSelected = option.series[hoveredIndex].pieStatus.selected;
            isHovered = false;
            startRatio = option.series[hoveredIndex].pieData.startRatio;
            endRatio = option.series[hoveredIndex].pieData.endRatio;
            k = option.series[hoveredIndex].pieStatus.k;
            i = itemHeight == 0 ? option.series[hoveredIndex].pieData.value === option.series[0].pieData.value ? 35 : 10 : itemHeight;

            // 对当前点击的扇形，执行取消高亮操作（对 option 更新）
            option.series[hoveredIndex].parametricEquation = getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              i
            );
            itemHeight == 0 ? option.series[hoveredIndex].pieStatus.hovered = isHovered : itemHeight;

            // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
            hoveredIndex = '';
          }

          // 如果触发 mouseover 的扇形不是透明圆环，将其高亮（对 option 更新）
          if (params.seriesName !== 'mouseoutSeries') {
            // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
            isSelected = option.series[params.seriesIndex].pieStatus.selected;
            isHovered = true;
            startRatio = option.series[params.seriesIndex].pieData.startRatio;
            endRatio = option.series[params.seriesIndex].pieData.endRatio;
            k = option.series[params.seriesIndex].pieStatus.k;

            // 对当前点击的扇形，执行高亮操作（对 option 更新）
            option.series[params.seriesIndex].parametricEquation = getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              itemHeight == 0 ? option.series[params.seriesIndex].pieData.value + 5 : itemHeight + 5
            );
            option.series[params.seriesIndex].pieStatus.hovered = isHovered;

            // 记录上次高亮的扇形对应的系列号 seriesIndex
            hoveredIndex = params.seriesIndex;
          }

          // 使用更新后的 option，渲染图表
          myChart.setOption(option);
        }
      });
      // 修正取消高亮失败的 bug
      myChart.on('globalout', function () {
        if (hoveredIndex !== '') {
          // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
          isSelected = option.series[hoveredIndex].pieStatus.selected;
          isHovered = false;
          k = option.series[hoveredIndex].pieStatus.k;
          startRatio = option.series[hoveredIndex].pieData.startRatio;
          endRatio = option.series[hoveredIndex].pieData.endRatio;
          // 对当前点击的扇形，执行取消高亮操作（对 option 更新）
          i = itemHeight == 0 ? option.series[hoveredIndex].pieData.value === option.series[0].pieData.value ? 35 : 10 : itemHeight;
          option.series[hoveredIndex].parametricEquation = getParametricEquation(
            startRatio,
            endRatio,
            isSelected,
            isHovered,
            k,
            i
          );
          option.series[hoveredIndex].pieStatus.hovered = isHovered;

          // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
          hoveredIndex = '';
        }

        // 使用更新后的 option，渲染图表
        myChart.setOption(option);
      });

      // 生成模拟 3D 饼图的配置项
      function getPie3D(pieData, internalDiameterRatio) {
        const series = [];
        // 总和
        let sumValue = 0;
        let startValue = 0;
        let endValue = 0;
        const legendData = [];
        const k =
          typeof internalDiameterRatio !== 'undefined'
            ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
            : 1 / 3;

        // 为每一个饼图数据，生成一个 series-surface 配置
        for (let i = 0; i < pieData.length; i += 1) {
          sumValue += pieData[i].value;

          const seriesItem = {
            name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
            type: 'surface',
            parametric: true,
            wireframe: {
              show: false,
            },
            pieData: pieData[i],

            itemStyle: {
              color: colors[i], // 自定义颜色
              opacity: '0.7'
            },
            pieStatus: {
              selected: false,
              hovered: false,
              k,
            },
          };

          if (typeof pieData[i].itemStyle !== 'undefined') {
            const { itemStyle } = pieData[i];

            // eslint-disable-next-line no-unused-expressions
            typeof pieData[i].itemStyle.color !== 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
            // eslint-disable-next-line no-unused-expressions
            typeof pieData[i].itemStyle.opacity !== 'undefined'
              ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
              : null;

            seriesItem.itemStyle = itemStyle;
          }
          series.push(seriesItem);
        }
        // 使用上一次遍历时，计算出的数据和 sumValue，调用 getParametricEquation 函数，
        // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation，也就是实现每一个扇形。
        console.log(series);
        for (let i = 0; i < series.length; i += 1) {
          endValue = startValue + series[i].pieData.value;

          series[i].pieData.startRatio = startValue / sumValue;
          series[i].pieData.endRatio = endValue / sumValue;

          series[i].parametricEquation = getParametricEquation(
            series[i].pieData.startRatio,
            series[i].pieData.endRatio,
            false,
            false,
            k,
            // 环形高度
            itemHeight == 0 ? series[i].pieData.value === series[0].pieData.value ? 35 : 10 : itemHeight
          );

          startValue = endValue;
          legendData.push(series[i].name);
        }

        // 准备待返回的配置项，把准备好的 legendData、series 传入。
        const option = {
          tooltip: {
            /** 保证 tooltip一直在图表内部 */
            position: function (point, params, dom, rect, size) {
              // size 中有两个属性：viewSize 和 contentSize，分别为 tooltip 的宽高
              // 这里设置的值都是为了保证 tooltip 内部显示
              var x = point[0];
              var y = point[1];
              var viewWidth = size.viewSize[0];
              var viewHeight = size.viewSize[1];
              var boxWidth = size.contentSize[0];
              var boxHeight = size.contentSize[1];

              // 判断 tooltip 位置，调整其位置使其不会超出图表边界
              if (x + boxWidth > viewWidth) {
                x = x - boxWidth;
              }
              if (y + boxHeight > viewHeight) {
                y = y - boxHeight;
              }

              // 保证 tooltip 始终在图表内部
              if (x < 0) {
                x = 0;
              }
              if (y < 0) {
                y = 0;
              }

              return [x, y];
            },
            formatter: (params) => {
              // if (params.seriesName !== 'mouseoutSeries') {
              //   return `
              //  ${params.seriesName}<br/>
              //     <span style="display:inline-block;
              //     margin-right:5px;
              //     border-radius:10px;
              //     width:10px;
              //     height:10px;
              //     background-color:${params.color};"></span>
              //     ${option.series[params.seriesIndex].pieData.value}
              //     `;
              // }
              if (params.seriesName !== 'mouseoutSeries') {
                return `
               ${option.series[params.seriesIndex].pieData.num}种<br/>
                  <span style="display:inline-block;
                  margin-right:5px;
                  border-radius:10px;
                  width:10px;
                  height:10px;
                  background-color:${params.color};"></span>
                  ${option.series[params.seriesIndex].pieData.type}
                  `;
              }
              return '';
            },
          },
          grid: {
            top: '2%',
            left: '0',
            right: '0',
            bottom: '0',
            containLabel: true
          },
          legend: {
            left: 'center', // 左边界对齐方式，这里使用'center'是为了让图例居中，你也可以根据需要调整为'left'或'right'
            bottom: "5%", // 底部对齐
            orient: 'horizontal',
            data: ['安徽省', '贵州省', '江西省', '四川省'],
            textStyle: {
              color: 'rgba(255, 255, 255, 0.8)' // 设置图例文字颜色为红色
            }
          },
          xAxis3D: {
            min: -1,
            max: 1,
          },
          yAxis3D: {
            min: -1,
            max: 1,
          },
          zAxis3D: {
            min: -1,
            max: 1,
          },
          grid3D: {
            show: false,
            boxHeight: 5,
            top: '0',
            left: '0',
            viewControl: { //3d效果可以放大、旋转等，请自己去查看官方配置
              alpha: 30, //角度(这个很重要 调节角度的)
              distance: 200,//调整视角到主体的距离，类似调整zoom(这是整体大小)
              rotateSensitivity: 10, //设置旋转灵敏度，为0无法旋转
              zoomSensitivity: 10, //设置缩放灵敏度，为0无法缩放
              panSensitivity: 10, //设置平移灵敏度，0无法平移
              autoRotate: true, //自动旋转
              autoRotateAfterStill: 1,//在鼠标静止操作后恢复自动旋转的时间间隔,在开启 autoRotate 后有效
            },
          },
          series,
        };
        return option;
      }

      // 生成图表，第二个参数为调整内环大小 0为实心圆饼图，大于0 小于1 为圆环
      const option = getPie3D(optionsData, .5);

      myChart.setOption(option);
    },
    initChart3() {
      const myChart = echarts.init(this.$refs.echartsLeft3); //初始化容器

      const data = [{
        name: '安徽省',
        value: '24'
      }, {
        name: '贵州省',
        value: '26'
      }, {
        name: '江西省',
        value: '38'
      }, {
        name: '四川省',
        value: '12'
      },]
      const option = {
        //你的代码
        color: [
          "#5AF3B8",
          "#93DBFF",
          "#4D74FF",
          "#FFD982"
        ],
        tooltip: {
          trigger: 'item',
          backgroundColor: 'rgba(3,50,86,0.8)',
          textStyle: {
            fontSize: 16,
            color: '#ffffff',
          },
          formatter: (params) => {
            return params.name + ': ' + params.value + '%'
          },
        },
        legend: {
          //图例形状
          icon: 'circle',
          left: 'center', // 左边界对齐方式，这里使用'center'是为了让图例居中，你也可以根据需要调整为'left'或'right'
          bottom: "5%", // 底部对齐
          show: true,
          data: data.map((el) => el.name),
          textStyle: {
            fontSize: 14,
            color: 'rgba(255, 255, 255, 0.64)',
          },
        },
        series: [
          {
            type: 'pie',
            roseType: 'radius',
            radius: ['25%', '60%'],
            center: ['50%', '50%'],
            data: data,
            itemStyle: {
              borderWidth: 2,
            },
            labelLine: {
              length: 0,
            },
            label: {
              formatter: (params) => {
                return '{name|' + params.name + ': }{value|' + params.value + '%}'
              },
              rich: {
                name: {
                  fontSize: 14,
                  color: '#a6e4ff',
                },
                value: {
                  fontSize: 14,
                  color: '#fff',
                },
              },
            },
          },
          {
            type: 'pie',
            radius: ['15%', '25%'],
            center: ['50%', '50%'],
            data: data,
            itemStyle: {
              opacity: 0.3,
            },
            label: {
              show: false,
            },
          },
        ],
      };

      myChart.setOption(option);
    },
    initChart4() {
      const myChart = echarts.init(this.$refs.echartsLeft4); //初始化容器
      var ydata = ['黄芪基地', '栀子基地', '浙贝母基地', '元胡基地'];
      const option = {
        //你的代码
        tooltip: {
          trigger: 'axis',
          // axisPointer: {
          //     type: 'cross',
          //     crossStyle: {
          //         color: '#999'
          //     }
          // }
        },
        grid: {
          top: '20%',
          left: '2%',
          right: '0',
          bottom: '0',
          containLabel: true
        },
        legend: {
          top: "5%",
          right: '0',
          itemWidth: 8,
          itemHeight: 8,
          orient: 'horizontal',
          data: ['面积数量', '农户数量'],
          textStyle: {
            color: 'rgba(255, 255, 255, 0.8)' // 设置图例文字颜色为红色
          }
        },
        xAxis: [
          {
            type: 'category',
            data: ydata,
            axisPointer: {
              type: 'shadow'
            },

            axisLine: {
              lineStyle: {
                color: 'rgba(8, 116, 229, 0.65)'
              }
            },
            axisLabel: {
              color: "rgba(255, 255, 255, 0.8)",
              show: true
            },
          }
        ],
        yAxis: [
          {
            type: 'value',
            name: '单位：个',
            nameTextStyle: {
              color: 'rgba(255, 255, 255, 0.8)', // 设置文字颜色为红色
              //fontWeight: 'bold', // 设置文字为粗体
              fontSize: 12, // 设置文字大小为14px
              // 可以根据需要添加更多的样式属性
            },
            // min: 0,
            // max: 250,
            // interval: 50,
            splitLine: {
              show: true,
              lineStyle: {
                type: 'dashed',
                color: 'rgba(8, 116, 229, 0.3)'
              }
            },
            axisLabel: {
              color: "rgba(255, 255, 255, 0.8)",
              show: true
            }
          }
        ],
        series: [
          {
            name: '面积数量',
            type: 'bar',
            color: '#165DFF',
            tooltip: {
              valueFormatter: function (value) {
                return value;
              }
            },
            data: [
              2.0, 4.9, 7.0, 23.2
            ],
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: '#0783FA' // 起始颜色（不透明）
                },
                {
                  offset: 1,
                  color: 'rgba(7, 131, 250, 0)' // 结束颜色（完全透明）
                }
              ])
            }
          },
          {
            name: '农户数量',
            type: 'bar',
            color: '#2CB8C5',
            tooltip: {
              valueFormatter: function (value) {
                return value;
              }
            },
            data: [
              2.6, 5.9, 9.0, 26.4
            ],
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: '#07D1FA' // 起始颜色（不透明）
                },
                {
                  offset: 1,
                  color: 'rgba(7, 131, 250, 0)' // 结束颜色（完全透明）
                }
              ])
            }
          }
        ]
      };

      myChart.setOption(option);
    },
    closeVideo() {
      this.showVideo = false;
    },
    openVideo() {
      this.showVideo = true;
      setTimeout(() => {
        this.initPlayer();
      }, 100);
    },
    initPlayer() {
      var dp = new DPlayer({
        container: document.getElementById('dplayer'),
        autoplay: true,
        theme: '#0093ff',
        loop: true,
        lang: 'zh-cn',
        screenshot: true,
        hotkey: true,
        preload: 'auto',
        volume: 0.7,
        mutex: true,
        // logo: 'https://i.loli.net/2019/06/06/5cf8c5d94521136430.png',
        video: {
          //   type: 'customHls',
          url: '/resource/video/902ced2937ab41dfa8caef50935cdc66_c.mp4',
          type: 'auto'
          //   customType: {
          //     customHls: (video, player) => {
          //       console.log('查看传递的参数', video, player)
          //       const hls = new Hls()
          //       hls.loadSource(video.src)
          //       hls.attachMedia(video)
          //     }
          //   }
        }
        // contextmenu: [{
        //         text: 'custom1',
        //         link: 'https://github.com/DIYgod/DPlayer',
        //     },
        //     {
        //         text: 'custom2',
        //         click: (player) => {
        //             console.log(player);
        //         },
        //     },
        // ],
      })
    },
    warnNotify() {
      this.$notify({
        title: '警告',
        message: '这是一条警告的提示消息',
        type: 'warning'
      });
    },
    handelObject(item, status) {
      this.singleObject = item;
      this.dialogShow = true;
      this.isGj = status;
    },
    getRead(id) {
      request({
        url: `/api/system/infoSdk/ecg/edit`,
        method: "put",
        data: {
          id: id,
          isRead: 1
        }
      }).then((res) => {
        this.getlist1();
        this.dialogShow = false;
      })
    },
    timestampToTime(timestamp) {
      var date = new Date(timestamp);
      var year = date.getFullYear();
      var month = date.getMonth() + 1;
      var day = date.getDate();
      var hours = date.getHours();
      var minutes = date.getMinutes();
      var seconds = date.getSeconds();
      var time = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
      return time;
    },
    testmqttSocket() {
      var that = this;
      // 创建一个连接到MQTT broker的客户端实例
      const client = mqtt.connect('ws://8.129.14.144:8083/mqtt', {
        username: "admin",
        password: "Guanxun2024",
      })
      this.client = client;
      // 连接成功后，订阅一个主题
      client.on('connect', function () {
        client.subscribe('mqtt/monitor/00042284049530907085', function (err) {
          if (!err) {
            console.log(`成功订阅 ${'mqtt/monitor/00042284049530907085'} 主题！`)
          }
        })
      })
      // 监听订阅主题上的消息
      client.on('message', function (topic, message) {

        console.log(topic);
        console.log(message.toString('utf-8'));
        var test = message.toString('utf-8');
        debugger
      })
    },
    mqttSocket() {
      var that = this;
      let deptId = this.$route.query.deptId || 2715; // John
      // 创建一个连接到MQTT broker的客户端实例
      const client = mqtt.connect('wss://fytx.91btg.cn:5356//mqttwss', this.config)
      this.client = client;
      // 连接成功后，订阅一个主题
      client.on('connect', function () {
        client.subscribe('mqtt/ecg/' + deptId, function (err) {
          if (!err) {
            console.log(`成功订阅 ${'mqtt/ecg/' + deptId} 主题！`)
          }
        })
      })
      // 监听订阅主题上的消息
      client.on('message', function (topic, message) {
        // 假设接收到的消息是Buffer类型
        // const msg = message.toString('utf8');
        // // 使用 decodeURIComponent 或 decodeURI 进行解码
        // const decodedMsg = decodeURIComponent(msg);
        // console.log(decodedMsg);
        // return false;
        if (topic === 'mqtt/ecg/' + deptId) {
          var parsedMessage = JSON.parse(decodeURIComponent(message.toString('utf-8')));
          parsedMessage.createTime = that.timestampToTime(parsedMessage.createTime);
          // 处理接收到的消息
          console.log('收到主题 ' + topic + ' 的消息: ' + parsedMessage.toString())
          that.cjlist.unshift(parsedMessage);
          if (parsedMessage.avgHrDescription == 'HIGH' || parsedMessage.avgHrDescription == 'LOW') {
            that.gjlist.unshift(parsedMessage);
            that.warnNotify();
            return false;
          }
          if (parsedMessage.avgQrsDescription == 'HIGH' || parsedMessage.avgQrsDescription == 'LOW') {
            that.gjlist.unshift(parsedMessage);
            that.warnNotify();
            return false;
          }
          if (parsedMessage.avgQtcDescription == 'HIGH' || parsedMessage.avgQtcDescription == 'LOW') {
            that.gjlist.unshift(parsedMessage);
            that.warnNotify();
            return false;
          }
          if (parsedMessage.avgPrIntervalsDescription == 'HIGH' || parsedMessage.avgPrIntervalsDescription == 'LOW') {
            that.gjlist.unshift(parsedMessage);
            that.warnNotify();
            return false;
          }
          if (parsedMessage.avgPDescription == 'HIGH' || parsedMessage.avgPDescription == 'LOW') {
            that.gjlist.unshift(parsedMessage);
            that.warnNotify();
            return false;
          }
          if (parsedMessage.scoreDescription == 'SEVERE') {
            that.gjlist.unshift(parsedMessage);
            that.warnNotify();
            return false;
          }
        }

      })
    },
    getDict(type) {
      request({
        url: `/api/system/infoSdk/type/${type}`,
        method: "get",
      }).then((res) => {
        if ('ecg_level' == type) {
          this.ecgLevel = this.arrayToDict(res.data);
        }
        if ('health_level' == type) {
          this.healthLevel = this.arrayToDict(res.data);
        }
        if ('diag_labels' == type) {
          this.diagLevel = this.arrayToDict(res.data);
          // console.log(this.diagLevel);
        }

      })
    },
    arrayToDict(arr) {
      const dict = {};
      for (let i = 0; i < arr.length; i++) {
        dict[arr[i].dictValue] = arr[i].dictLabel;
      }
      return dict;
    },
    formatLocalDate(date) {
      return (
        date.getFullYear() + '-' +
        (date.getMonth() + 1).toString().padStart(2, '0') + '-' +
        date.getDate().toString().padStart(2, '0')
      );
    },
    getThreeDay() {
      var date = new Date();
      date.setDate(date.getDate() - 3);//获取3天前的日期
      var year = date.getFullYear();
      var month = date.getMonth() + 1;
      if (month < 10) {
        month = '0' + month;
      }
      var day = date.getDate();
      if (day < 10) {
        day = '0' + day;
      }
      return year + "-" + month + "-" + day;
    },
    getlist() {
      let deptId = this.$route.query.deptId || 2715; // John
      var params = {
        deptId: deptId,
        // params['beginTime']:this.getThreeDay(),
        // params['endTime']:this.formatLocalDate(new Date()),
        // params:{
        //   beginTime: this.getThreeDay(),
        //   endTime: this.formatLocalDate(new Date())
        // }
      };
      const queryString = new URLSearchParams(params).toString();
      request({
        url: "/api/system/infoSdk/ecgList?" + encodeURI("params['beginTime']=" + this.getThreeDay() + "&params['endTime']=" + this.formatLocalDate(new Date())) + "&" + queryString,
        method: "get",
      }).then((res) => {
        this.isVisibleCj = false;
        this.$nextTick(() => {
          this.isVisibleCj = true;
          this.cjlist = res.data;
        });
      })
    },
    getlist1() {
      let deptId = this.$route.query.deptId || 2715; // John
      var params = {
        scoreDescription: "MODERATE,MILD,SEVERE",
        isRead: 0,
        deptId: deptId,
        // params['beginTime']:this.getThreeDay(),
        // params['endTime']:this.formatLocalDate(new Date()),
        // params:JSON.stringify({
        //   beginTime: this.getThreeDay(),
        //   endTime: this.formatLocalDate(new Date())
        // })
      };
      const queryString = new URLSearchParams(params).toString();

      request({
        url: "/api/system/infoSdk/ecgList?" + encodeURI("params['beginTime']=" + this.getThreeDay() + "&params['endTime']=" + this.formatLocalDate(new Date())) + "&" + queryString,
        method: "get",
      }).then((res) => {
        this.isVisibleGj = false;
        this.$nextTick(() => {
          this.isVisibleGj = true;
          this.gjlist = res.data;
        });
      })
    },
    // 地图状态切换
    mapStatusSwitch(e) {
      // 地图状态数组
      const mapStatusArr = ["国", "省", "市"];
      // 当前地图状态在mapStatusArr中的下标位置
      let index = mapStatusArr.indexOf(this.mapStatus);
      // left表示鼠标左键双击触发，地图状态进入下一层，国=>省=>市
      if (e === "left") {
        index++;
      }
      // right表示鼠标右键键双击触发，地图状态返回上一层，市=>省=>国
      else if (e === "right") {
        index--;
      }
      // 重新定义地图状态
      if (mapStatusArr[index]) this.mapStatus = mapStatusArr[index];
    },
    // 循环渲染
    render() {
      requestAnimationFrame(this.render);
      camera.updateProjectionMatrix();
      controls.update();
      // 两帧渲染间隔
      let deltaTime = this.clock.getDelta();
      // 地图模型侧边渐变效果
      mapUf.uTime.value += deltaTime;
      if (mapUf.uTime.value >= 5) {
        mapUf.uTime.value = 0.0;
      }
      // 地图光圈动态缩放动画
      apertureArr.map((mesh) => {
        // _s缩放值累加
        mesh._s += 0.05;
        // 小于20时，逐渐透明度逐渐增加到1
        if (mesh._s <= 20.0) {
          mesh.material.opacity = (mesh._s - 10.0) * 0.1;
        }
        // 20-30之间时，透明度逐渐递减到0
        else if (mesh._s > 20.0 && mesh._s <= 30) {
          mesh.material.opacity = 1 - (mesh._s - 20.0) / 10;
        }
        // 大于30进行重置
        else {
          mesh._s = 10.0;
        }
        // 设置新的缩放值
        mesh.scale.set(mesh._s, mesh._s, mesh._s);
      });
      // 背景外圈内圈旋转
      outerCircle.rotation.z -= 0.003;
      innerCircle.rotation.z += 0.003;
      // 飞线动画
      // if (rightButItem[2].selected) {
      //   flyLineAnimation();
      // }
      // 波纹扩散动画
      if (this.rightButItem[2].selected) {
        circleUf.uTime.value += deltaTime;
        if (circleUf.uTime.value >= 6) {
          circleUf.uTime.value = 0.0;
        }
      }
      // 粒子动画
      if (this.rightButItem[4].selected) {
        particlesUpdate();
      }
      css3DRenderer.render(scene, camera);
      css2DRenderer.render(scene, camera);
      // TWEEN更新
      TWEEN.update();
      // 将场景内的物体材质设置为黑色
      scene.traverse(this.darkenMaterial);
      // 渲染辉光
      composer.render();
      // 还原材质
      scene.traverse(this.restoreMaterial);
      // 最终渲染
      finalComposer.render();
    },
    // 右侧按钮点击事件
    rightButClick(e, item) {
      // 当前按钮点击项
      let clickItem;
      //  代码中触发的点击项
      if (item) {
        clickItem = item;
      }
      // 用户手动点击触发的点击项
      else {
        const value = e.target.getAttribute("value");
        clickItem = this.rightButItem.filter((obj) => obj.value === value)[0];
        clickItem.selected = !clickItem.selected;
      }
      // 点击刷色图按钮
      if (clickItem.value === "tourism") {
        mapModel.traverse((item) => {
          if (item.color) {
            if (clickItem.selected) {
              item.material[0].color = item.color;
              item.material[0].metalness = 0.5;
              item.material[0].map = undefined;
              item.material[0].needsUpdate = true;
            } else {
              item.material[0].color = new THREE.Color("#00FFFF");
              item.material[0].metalness = 0.0;
              item.material[0].map = item.texture;
              item.material[0].needsUpdate = true;
            }
          }
        });
      }
      // 点击飞线按钮
      else if (clickItem.value === "flyLine") {
        if (clickItem.selected) {
          scene.add(flyGroup);
          updateFlyLine("湖北", cityData);
        } else {
          scene.remove(flyGroup);
        }
      }
      // 点击棱柱按钮
      else if (clickItem.value === "prism") {
        if (clickItem.selected) {
          scene.add(prismGroup);
        } else {
          for (const iterator of prismGroup.children) {
            if (iterator.children[0].element) {
              css2DRenderer.domElement.removeChild(iterator.children[0].element); // 重点
            }
          }
          scene.remove(prismGroup);
        }
      }
      // 点击波纹按钮
      else if (clickItem.value === "ripple") {
        if (clickItem.selected) {
          diffuseCircle.visible = true;
        } else {
          diffuseCircle.visible = false;
        }
        circleUf.uTime.value = 0.0;
      }
      // 点击倒影按钮
      else if (clickItem.value === "mirror") {
        if (clickItem.selected) {
          scene.add(mirror);
          planeUf.opacitys.radius = 0.3;
          planeUf.opacitys.value = 0.5;
        } else {
          scene.remove(mirror);
          planeUf.opacitys.radius = 0.24;
          planeUf.opacitys.value = 0.7;
        }
      }
      // 点击标牌按钮
      else if (clickItem.value === "tag") {
        if (clickItem.selected) {
          scene.add(tagGroup);
        } else {
          for (const iterator of tagGroup.children) {
            css2DRenderer.domElement.removeChild(iterator.element); // 重点
          }
          scene.remove(tagGroup);
        }
      }
      // 点击粒子按钮
      else if (clickItem.value === "particles") {
        if (clickItem.selected) {
          scene.add(particles);
        } else {
          scene.remove(particles);
        }
      }
    },
    // 初始化地图点击发光效果
    initMapClickGlow() {
      this.divTag = document.getElementById("popup");
      const widthScale = window.innerWidth / 1920;
      const heightScale = window.innerHeight / 941;
      this.divTag.style.top += (37 * heightScale).toFixed(2) + "px";
      this.divTag.style.left += (390 * widthScale).toFixed(2) + "px";
      // 转换为CSS2D对象
      this.css2Dpopup = new CSS2DObject(this.divTag);
      this.css2Dpopup.name = "弹框";
      // 设置一个较高的渲染顺序，防止弹框被标牌等物体遮挡住
      this.css2Dpopup.renderOrder = 99;
      // 弹框名称元素
      // const nameDiv = document.getElementById("popup_Name");
      // 鼠标点击事件
      addEventListener("click", (e) => {

        if (mapModel.visible) {
          const px = e.offsetX;
          const py = e.offsetY;
          this.map.left = px;
          this.map.right = py;
          // 屏幕坐标转为标准设备坐标
          const x = (px / window.innerWidth) * 2 - 1;
          const y = -(py / window.innerHeight) * 2 + 1;
          // 创建射线
          const raycaster = new THREE.Raycaster();
          // 设置射线参数
          raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
          // 射线交叉计算拾取模型
          let intersects = raycaster.intersectObjects(mapModel.children);
          // 检测结果过滤掉光圈
          intersects = intersects.filter(function (intersect) {
            return intersect.object.name !== "光圈";
          });
          // 点击选中模型时
          if (intersects.length > 0) {
            // 清除上一次添加的发光模型
            if (this.rayObj) {
              this.rayObj.remove(this.glowModel);
            }
            const parent = intersects[0].object.parent;
            console.log(intersects[0].object, "intersects[0].object");
            console.log(parent, "parent");
            if (parent) {
              // 射线第一个拾取中的模型
              const lastModel = parent.name && parent.name !== "省份边线" ? parent : parent.parent;
              this.rayObj = lastModel.getObjectByName("省份边线");
              if (this.rayObj.parent.name && this.rayObj.userData.center) {
                this.map.showLayer = true;
                // // 设置弹框位置，弹框名称等
                // const center = this.rayObj.userData.center;
                // this.css2Dpopup.position.set(center[0], center[1], 0);
                // this.rayObj.add(this.css2Dpopup);
                // // nameDiv.innerHTML = this.rayObj.parent.name;

                // // 给弹框加载创建渐变动画
                // new TWEEN.Tween({ opacity: 0 })
                //   .to({ opacity: 1.0 }, 500)
                //   .onUpdate(function (obj) {
                //     this.divTag = document.getElementById("popup");
                //     //动态更新div元素透明度
                //     this.divTag.style.opacity = obj.opacity;
                //   })
                //   .start();
                // // 更新飞线为选中的省份模型
                // if (this.rightButItem[2].selected) {
                //   // updateFlyLine(lastModel.name, cityData);
                // }
                // // 地图边线数据
                // const mapLineData = this.rayObj.userData.cityData;
                // // 创建shape对象
                // const shape = new THREE.Shape();
                // // 当数据为多个多边形时
                // if (mapLineData.type === "MultiPolygon") {
                //   // 遍历数据，绘制shape对象数据
                //   mapLineData.coordinates.forEach((coordinate, index) => {
                //     if (index === 0) {
                //       coordinate.forEach((rows) => {
                //         rows.forEach((row) => {
                //           const [x, y] = projection(row);
                //           if (index === 0) {
                //             shape.moveTo(x, y);
                //           }
                //           shape.lineTo(x, y);
                //         });
                //       });
                //     }
                //   });
                // }
                // // 当数据为单个多边形时
                // if (mapLineData.type === "Polygon") {
                //   mapLineData.coordinates.forEach((coordinate) => {
                //     // 遍历数据，绘制shape对象数据
                //     mapLineData.coordinates.forEach((rows, index) => {
                //       if (index === 0) {
                //         rows.forEach((row) => {
                //           const [x, y] = projection(row);
                //           if (index === 0) {
                //             shape.moveTo(x, y);
                //           }
                //           shape.lineTo(x, y);
                //         });
                //       }
                //     });
                //   });
                // }
                // // 创建形状几何体，shape对象作为参数
                // const geometry = new THREE.ShapeGeometry(shape);
                // const material = new THREE.MeshBasicMaterial({
                //   color: lastModel.children[1].material[0].color,
                //   map: lastModel.children[1].material[0].map,
                //   side: THREE.DoubleSide,
                // });
                // let mesh = new THREE.Mesh(geometry, material);
                // mesh.rotateX(-Math.PI);
                // // mesh.position.y += 1;
                // mesh.name = "发光模型";
                // this.glowModel = mesh;
                // this.rayObj.add(this.glowModel);
                // // 设置发光模型进行发光
                // outlinePass.selectedObjects = [this.glowModel];
              }
            }
          }
          // 未选中模型
          else {
            this.map.showLayer = false;
            if (this.glowModel) {
              outlinePass.selectedObjects = [];
              this.rayObj.remove(this.glowModel);
              // 给弹框清除创建渐变动画
              new TWEEN.Tween({ opacity: 1 })
                .to({ opacity: 0 }, 500)
                .onUpdate(function (obj) {
                  //动态更新div元素透明度
                  this.divTag = document.getElementById("popup");
                  this.divTag.style.opacity = obj.opacity;
                })
                .onComplete(function () {
                  if (this.css2Dpopup) {
                    // 清除弹框
                    this.rayObj.remove(this.css2Dpopup);
                  }

                })
                .start();
            }
          }
        }
      });
    },
    // 弹框关闭事件
    popupClose() {
      if (this.glowModel) {
        outlinePass.selectedObjects = [];
        this.rayObj.remove(this.glowModel);
        // this.rayObj.visible = false;
        // 给弹框清除创建渐变动画
        new TWEEN.Tween({ opacity: 1 })
          .to({ opacity: 0 }, 500)
          .onUpdate(function (obj) {
            //动态更新div元素透明度
            this.divTag = document.getElementById("popup");
            this.divTag.style.opacity = obj.opacity;
          })
          .onComplete(function () {
            if (this.css2Dpopup) {
              // 清除弹框
              this.rayObj.remove(this.css2Dpopup);
            }

          })
          .start();
      }
    },
    // 将材质设置成黑色
    darkenMaterial(obj) {
      // 场景颜色单独保存
      if (obj instanceof THREE.Scene) {
        obj.bg = obj.background;
        obj.background = null;
      }

      const material = obj.material;
      if (material && !this.glowArr.includes(obj)) {
        obj.originalMaterial = obj.material;
        const Proto = Object.getPrototypeOf(material).constructor;
        // 镜面倒影的颜色单独保存
        if (obj.type === "Reflector") {
          obj.userData.color = new THREE.Color("#696969");
        } else {
          obj.material = new Proto({ color: new THREE.Color("#000") });
        }
      }
    },
    // 还原材质
    restoreMaterial(obj) {
      if (obj instanceof THREE.Scene) {
        obj.background = obj.bg;
      }
      if (obj.type === "Reflector") {
        obj.material.uniforms.color.value = obj.userData.color;
      }
      if (!obj.originalMaterial) return;
      obj.material = obj.originalMaterial;
      delete obj.originalMaterial;
    },
    // 首次进入动画
    eventAnimation() {
      new TWEEN.Tween(camera.clone().position)
        .to(new THREE.Vector3(-5, 250, 150), 1500)
        .easing(TWEEN.Easing.Sinusoidal.InOut)
        .onUpdate((e) => {
          camera.position.copy(e);
          controls.target.set(-5, 0, 10);
          controls.update();
        })
        .start();
    },
    // 初始化地图右键双击切换到省份事件
    initMapDoubleClick() {
      // 最后右键点击时间
      let lastRightClickTime = 0;
      addEventListener("contextmenu", (e) => {
        e.preventDefault(); // 防止浏览器弹出右键菜单
        const currentTime = Date.now();
        const timeSinceLastClick = currentTime - lastRightClickTime;
        // 两次右键点击间隔小于300则视为双击
        if (timeSinceLastClick < 300) {
          // 全国地图切换到省份地图
          if (this.mapStatus !== "市") {
            // 关闭右侧按钮的显示
            // this.rightButton.style.display = "none";
            // 获取鼠标当前位置坐标
            const px = e.offsetX;
            const py = e.offsetY;
            // 屏幕坐标转为标准设备坐标
            const x = (px / window.innerWidth) * 2 - 1;
            const y = -(py / window.innerHeight) * 2 + 1;
            // 创建射线
            const raycaster = new THREE.Raycaster();
            // 设置射线参数
            raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
            // 射线交叉计算拾取模型，检测对象为全国地图模型
            let intersects = raycaster.intersectObjects(this.currentShowModel.children);
            // 检测结果过滤掉光圈
            intersects = intersects.filter(function (intersect) {
              return intersect.object.name !== "光圈" && intersect.object.name !== "发光模型" && intersect.object.type !== "Line";
            });
            // 点击选中模型时
            if (intersects.length > 0) {
              // 选中模型的父级对象，因为一般选中的都是某个地级市，需要获取到整个省份对象
              const parent = intersects[0].object.parent.clone();
              // 判断是否选中的省份边线，如果是还要向上获取一次父级对象
              const closeModel = parent.name !== "省份边线" ? parent : parent.parent;
              // 删除掉省份模型里的弹框
              closeModel.children[0].remove(closeModel.getObjectByName("弹框"));
              closeModel.children[0].remove(closeModel.getObjectByName("省份名称"));
              // closeModel.remove(closeModel.getObjectByName("弹框"));
              // 触发右侧按钮点击事件，将效果清除
              this.rightButItem.map((item) => {
                // 只需要清除选中状态的项目
                if (item.selected) {
                  item.selected = false;
                  this.rightButClick(null, item);
                }
                // 打开倒影
                if (item.value === "mirror") {
                  item.selected = true;
                  this.rightButClick(null, item);
                }
              });
              console.log(closeModel, "点击的模型");
              // 切换到省份地图
              this.switchProvinceMap(closeModel);
            }
          }
          // 省份地图切换到全国地图
          else {
            // rightButton.value.style.display = "block";
            // // 删除掉模型
            // currentShowModel.value.traverse((item) => {
            //   if (item.element) {
            //     item.element.parentNode.removeChild(item.element);
            //   }
            // });
            // currentShowModel.value.children = [];
            // mapStatusSwitch("right");
            // currentShowModel.value.visible = true;
            // currentShowModel.value.traverse((item) => {
            //   item.visible = true;
            // });
          }
        }
        lastRightClickTime = currentTime;
      });
    },
    returns() {
      // this.rightButton.style.display = "block";
      // 删除掉模型
      // currentShowModel.value.traverse((item) => {
      //   if (item.element) {
      //     item.element.parentNode.removeChild(item.element);
      //   }
      // });
      // currentShowModel.value.children = [];

      this.disposeObject(this.currentShowModel);

      this.mapStatusSwitch("right");
      this.currentShowModel.visible = true;
      this.currentShowModel.traverse((item) => {
        item.visible = true;
      });

      if (this.mapStatus != "国") {
        return;
      }

      // 触发右侧按钮点击事件，将效果清除
      this.rightButItem.map((item) => {
        // 只需要清除选中状态的项目
        if (item.selected) {
          item.selected = false;
          this.rightButClick(null, item);
        }
        // 打开标牌
        if (item.value === "tag") {
          item.selected = true;
          this.rightButClick(null, item);
        }
      });
    },
    disposeObject(obj) {
      const materialMaps = ["map", "alphaMap", "aoMap", "bumpMap", "displacementMap", "emissiveMap", "envMap", "lightMap", "metalnessMap", "normalMap", "roughnessMap", "specularMap"];
      if (obj.traverse) {
        obj.traverse((item) => {
          // 释放几何体
          if (item.geometry) {
            item.geometry.dispose();
          }

          // 释放材质和纹理
          if (item.material) {
            if (Array.isArray(item.material)) {
              item.material.forEach((material) => {
                materialMaps.forEach((mapName) => {
                  if (material[mapName]) {
                    material[mapName].dispose();
                  }
                });
                material.dispose();
              });
            } else {
              materialMaps.forEach((mapName) => {
                if (item.material[mapName]) {
                  item.material[mapName].dispose();
                }
              });
              item.material.dispose();
            }
          }

          // 清除CSS2D/3D对象dom元素
          if (item.isCSS2DObject || item.isCSS3DObject) {
            if (item.element && item.element.parentNode) {
              item.element.parentNode.removeChild(item.element);
            }
          }
        });
      }
      obj.children = [];
    },
    // 切换到省份地图
    async switchProvinceMap(selectModel) {
      // const statusArr = ["国", "省", "市"];
      // const mapArr = [mapModel, provinceModel, cityModel];
      // console.log(mapArr[statusArr.indexOf(mapStatus.value)], "mapArr[statusArr.indexOf(mapStatus.value)]");
      // mapArr[statusArr.indexOf(mapStatus.value)].visible = false;
      // mapArr[statusArr.indexOf(mapStatus.value)].traverse((item) => {
      //   item.visible = false;
      // });

      this.currentShowModel.visible = false;
      this.currentShowModel.traverse((item) => {
        item.visible = false;
      });
      this.mapStatusSwitch("left");

      // // 隐藏掉全国地图模型
      // mapModel.traverse((item) => {
      //   item.visible = false;
      // });
      // 计算选中的省份模型大小，根据每个省份模型大小不同得出一个缩放值
      const box = new THREE.Box3().setFromObject(selectModel.clone());
      // 计算模型的长宽
      const length = box.max.x - box.min.x;
      const width = box.max.z - box.min.z;
      // 根据模型大小计算一个缩放值

      const factor = this.mapStatus == "省" ? 1.4 : 2;
      const boxSize = (length + width) / factor;
      let scale = this.size / boxSize;

      // if (mapStatus.value == "市") scale = scale + provinceSize;
      console.log(this.mapStatus, "mapStatus.value");
      console.log(boxSize, "boxSize");
      console.log(this.size, "size");
      console.log(scale, "scale");
      this.provinceSize = scale;
      // 应用缩放值到省份模型上去，最低缩放值为2倍
      // currentShowModel.value.scale.set(scale, scale, 1);
      this.currentShowModel.scale.set(scale, scale, 1);
      // 绘制省份模型内的地级市模型，这里异步处理，要等地级市模型绘制完毕才能执行后面的计算处理
      await this.drawCityModel(selectModel.clone());
      // 这时候计算省份模型，得出放大后的省份模型的中心点，并将其位置归于原点
      const scaledBox = new THREE.Box3().setFromObject(this.currentShowModel);
      const center = new THREE.Vector3();
      // 获取放大后模型的中心点
      scaledBox.getCenter(center);
      // 将模型的位置调整，使缩放后的中心位于原点
      this.currentShowModel.position.sub(center);
      // 高度不增加
      this.currentShowModel.position.y += center.y;

      // 显示省份模型
      this.currentShowModel.visible = true;
      console.log(this.currentShowModel, "currentShowModel.value");
    },

    // 绘制城市模型
    async drawCityModel(selectModel) {
      // console.log(selectModel, "selectModel");
      // 地级市json数据地址
      const url = this.mapStatus == "省" ? "http://117.159.12.79:18061/file/geojson/province/" : "http://117.159.12.79:18061/file/geojson/citys/";
      // const url = `http://117.159.12.79:18061/file/geojson/province/${selectModel.userData.adcode}.json`;
      // 选中省份模型的材质，将继续应用到地级市模型上
      const materialArr = selectModel.clone().children[this.mapStatus == "省" ? 1 : 0].material;
      // console.log(materialArr, "materialArr");
      // 获取地级市数据
      await new Promise((resolve) => {
        fetch(url + selectModel.userData.adcode + ".json")
          .then((response) => response.json())
          .then((data) => {
            // 全部信息
            const features = data.features;
            features.map((feature) => {
              // 城市模型
              const cityModel = new THREE.Object3D();
              cityModel.name = feature.properties.name;
              cityModel.userData.animationActive = false; // 新增属性来跟踪动画状态
              cityModel.userData.animationTimer = null; // 用于存储定时器的引用
              cityModel.userData.adcode = feature.properties.adcode;

              this.currentShowModel.add(cityModel);
              // 创建地级市的名称对象
              const dom = document.getElementById("cityName").cloneNode();
              // 设置元素文本为地级市的名称
              dom.innerHTML = feature.properties.name;
              // 转为CSS3D对象
              const css3DObject = new CSS3DObject(dom);
              css3DObject.rotateX(Math.PI);
              css3DObject.name = "城市名称";
              // 这里转换完成后将元素pointerEvents属性设置为none，防止阻碍相机旋转缩放平移等操作
              dom.style.pointerEvents = "none";
              // 设置对应的位置
              const [x, y] = projection(feature.properties.center);
              css3DObject.position.set(x, -y, 0);
              css3DObject.rotateX(Math.PI);
              // 缩放一定大小
              css3DObject.scale.set(0.2 / this.currentShowModel.scale.x, 0.2 / this.currentShowModel.scale.x, 0.2 / this.currentShowModel.scale.x);
              const coordinates = feature.geometry.coordinates;
              // 绘制地级市边界线
              if (feature.geometry.type === "MultiPolygon") {
                coordinates.forEach((coordinate) => {
                  coordinate.forEach((rows) => {
                    // 选中省份模型的材质，将继续应用到地级市模型上
                    // const materialArr = selectModel.clone().children[1].material;
                    // 城市模型
                    const mesh = this.drawExtrudeMesh(rows, materialArr);
                    mesh.rotateX(Math.PI);
                    cityModel.add(mesh);
                    // 边线
                    const line = this.lineDraw(rows);
                    line.name = "边线";
                    line.position.z += 0.15;
                    cityModel.add(line, css3DObject);
                  });
                });
              }
              // 创建省份边界线和模型-单个多边形
              if (feature.geometry.type === "Polygon") {
                coordinates.forEach((coordinate) => {
                  // 选中省份模型的材质，将继续应用到地级市模型上
                  // const materialArr = selectModel.clone().children[1].material;
                  // 城市模型
                  const mesh = this.drawExtrudeMesh(coordinate, materialArr);
                  mesh.rotateX(Math.PI);
                  cityModel.add(mesh);
                  // 边线
                  const line = this.lineDraw(coordinate);
                  line.position.z += 0.15;
                  line.name = "边线";
                  cityModel.add(line, css3DObject);
                });
              }
            });
            resolve();
          });
      });
    },
    // 绘制模型
    drawExtrudeMesh(polygon, materialArr) {
      // 创建形状
      const shape = new THREE.Shape();
      // 遍历坐标数组，绘制形状
      polygon.forEach((row, i) => {
        // 坐标点转换
        const [x, y] = projection(row);
        if (i === 0) {
          shape.moveTo(x, y);
        }
        shape.lineTo(x, y);
      });
      // 将形状进行拉伸
      const geometry = new THREE.ExtrudeGeometry(shape, {
        depth: 10,
        bevelEnabled: true,
        bevelSegments: 10,
        bevelThickness: 0.1,
      });
      const topMaterial = materialArr[0].clone();
      const sideMaterial = materialArr[1];
      const mesh = new THREE.Mesh(geometry, [topMaterial, sideMaterial]);
      return mesh;
    },
    // 绘制边界线
    lineDraw(polygon) {
      const lineGeometry = new THREE.BufferGeometry();
      const pointsArray = new Array();
      polygon.forEach((row) => {
        const [x, y] = projection(row);
        // 创建三维点
        pointsArray.push(new THREE.Vector3(x, -y, 0));
      });
      // 放入多个点
      lineGeometry.setFromPoints(pointsArray);
      const lineMaterial = new THREE.LineBasicMaterial({
        color: "#00ffff",
        // color: "#00C5CD",
      });
      return new THREE.Line(lineGeometry, lineMaterial);
    }
  },
  destroyed() {
    this.client.end()
  }
}
</script>

<style lang="less" scoped>
@font-face {
  font-family: '汉仪神工体简';
  src: url('../../assets/fonts/汉仪神工体简.TTF');
}

@font-face {
  font-family: 'IMPACT';
  src: url('../../assets/fonts/IMPACT.TTF');
}

@font-face {
  font-family: 'YouSheBiaoTiHei';
  src: url('../../assets/fonts/YouSheBiaoTiHei-2.ttf');
}

.container {
  width: 100%;
  height: 100vh;
  background: url('../../assets/images/index/bg.png') no-repeat;
  background-size: cover;
  position: relative;
  overflow-y: hidden;

  .header {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 73px;
    background: url('../../assets/images/index/header.png') no-repeat;
    background-size: 100% 100%;
    color: #ffffff;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-between;
    z-index: 999;

    .logo_title {
      padding-left: 6.6%;
      font-size: 40px;
      letter-spacing: 3px;
      line-height: 73px;
      font-family: 'YouSheBiaoTiHei';
    }

    .nav {
      display: flex;
      flex-direction: row;
      flex-wrap: nowrap;
      justify-content: space-between;
      align-items: center;

      .item {
        width: 220px;
        height: 61px;
        background: url('../../assets/images/index/nav.png') no-repeat;
        font-size: 20px;
        line-height: 61px;
        font-weight: 500;
        background-size: 100% 100%;
        text-align: center;
        margin-right: -31px;
        cursor: pointer;
        margin-top: 10px;
      }

      .item.active {
        width: 220px;
        height: 61px;
        background: url('../../assets/images/index/nav_s.png') no-repeat;
        font-size: 20px;
        line-height: 61px;
        font-weight: 500;
        background-size: 100% 100%;
        text-align: center;
        margin-right: -31px;
      }

      .item:hover {
        width: 220px;
        height: 61px;
        background: url('../../assets/images/index/nav_s.png') no-repeat;
        font-size: 20px;
        line-height: 61px;
        font-weight: 500;
        background-size: 100% 100%;
        text-align: center;
        margin-right: -31px;
      }

      .item:last-child {
        width: 220px;
        height: 61px;
        background: url('../../assets/images/index/nav2.png') no-repeat;
        font-size: 20px;
        line-height: 61px;
        font-weight: 500;
        background-size: 100% 100%;
        text-align: center;
        box-sizing: border-box;
        padding-left: 21px;
        margin-right: 0;
      }

      .item:last-child:hover {
        width: 220px;
        height: 61px;
        background: url('../../assets/images/index/nav2_s.png') no-repeat;
        font-size: 20px;
        line-height: 61px;
        font-weight: 500;
        background-size: 100% 100%;
        text-align: center;
        box-sizing: border-box;
        padding-left: 21px;
        margin-right: 0;
      }

      .item:last-child.active {
        width: 220px;
        height: 61px;
        background: url('../../assets/images/index/nav2_s.png') no-repeat;
        font-size: 20px;
        line-height: 61px;
        font-weight: 500;
        background-size: 100% 100%;
        text-align: center;
        box-sizing: border-box;
        padding-left: 21px;
        margin-right: 0;
      }
    }
  }

  .left {
    width: 379px;
    position: absolute;
    top: 103px;
    left: 20px;
    z-index: 999;

    .title {
      width: 100%;
      height: 46px;
      background: url('../../assets/images/index/title.png') no-repeat;
      background-size: 100% 100%;
      line-height: 46px;
      font-size: 20px;
      text-align: left;
      text-indent: 31px;
      box-sizing: border-box;
      color: #ffffff;
    }

    .section:last-child {
      margin-bottom: 0px;
    }

    .section {
      width: 100%;
      margin-bottom: 10px;

      .content {
        width: 100%;
        height: calc(33vh - 87px);

        .echarts_subtitle {
          font-size: 12px;
          line-height: 16px;
          text-align: right;
          color: rgba(255, 255, 255, 0.8);
          margin: 8px 0;
        }

        .list {
          width: 100%;

          .item {
            width: 100%;

            .info {
              width: 100%;
              display: flex;
              flex-direction: row;
              flex-wrap: nowrap;
              justify-content: space-between;
              align-items: center;
              align-self: center;
              align-content: center;
              color: #ffffff;

              .sleft {
                display: flex;
                flex-direction: row;
                flex-wrap: nowrap;
                align-items: center;
                align-self: center;
                align-content: center;

                p.num {
                  width: 24px;
                  text-align: center;

                  img {
                    width: 24px;
                  }
                }

                p.name {
                  padding-left: 9px;
                  font-size: 16px;
                  font-weight: 600;
                  line-height: 36px;
                }
              }

              .sright {
                font-size: 16px;
                font-weight: 600;
                line-height: 36px;
              }
            }

            .porgressBox {
              width: 100%;
              height: 6px;
              background: rgba(255, 255, 255, 0.13);
              display: flex;
              flex-direction: row;

              .progressPer {
                width: 80%;
                height: 6px;
                background: linear-gradient(271deg, #29C6FA 1%, rgba(27, 126, 242, 0.49) 99%);
              }

              .progressAct {
                width: 2px;
                height: 8px;
                background: #FFFFFF;
                border-radius: 134px;
                position: relative;
                top: -1px
              }
            }
          }
        }

        .list1 {
          background: rgba(8, 107, 215, 0.05);
          width: 100%;
          line-height: 24px;
          font-size: 16px;

          .item.tab {
            font-weight: bold;
            color: #29F1FA;
          }

          .item {
            width: 100%;
            display: flex;
            flex-direction: row;
            flex-wrap: nowrap;
            justify-content: space-around;
            color: #fff;
            text-align: center;

            // p{
            //   padding: 10px 0;
            // }
            p:nth-child(1) {
              width: calc(50% - 55px);
            }

            p:nth-child(2) {
              width: calc(50% - 55px);
            }

            p:nth-child(3) {
              width: 66px;
            }

            p:last-child {
              width: 20px;
            }
          }
        }
      }
    }
  }

  .right {
    width: 379px;
    position: absolute;
    top: 103px;
    right: 20px;
    z-index: 999;

    .title {
      width: 100%;
      height: 46px;
      background: url('../../assets/images/index/title.png') no-repeat;
      background-size: 100% 100%;
      line-height: 46px;
      font-size: 20px;
      text-align: left;
      text-indent: 31px;
      box-sizing: border-box;
      color: #ffffff;
    }

    .section:last-child {
      margin-bottom: 0px;
    }

    .section {
      width: 100%;
      margin-bottom: 10px;

      .content {
        height: calc(33vh - 87px);
      }

      .content1 {
        height: calc(29vh - 87px);
        overflow-y: auto;
      }

      .content2 {
        height: calc(37vh - 110px);
        overflow-y: auto;
      }

      .content,
      .content1,
      .content2 {
        width: 100%;

        .list {
          width: 100%;

          .list1Warp {
            width: 100%;
            // height: 136px;
            height: calc(29vh - 40px);
            margin: 0 auto;
            overflow: hidden;
          }

          .item {
            width: 100%;

            .info {
              width: 100%;
              display: flex;
              flex-direction: row;
              flex-wrap: nowrap;
              justify-content: space-between;
              align-items: center;
              align-self: center;
              align-content: center;
              color: #ffffff;

              .sleft {
                display: flex;
                flex-direction: row;
                flex-wrap: nowrap;
                align-items: center;
                align-self: center;
                align-content: center;

                p.num {
                  width: 24px;
                  text-align: center;

                  img {
                    width: 24px;
                  }
                }

                p.name {
                  padding-left: 9px;
                  font-size: 16px;
                  font-weight: 600;
                  line-height: 36px;
                }
              }

              .sright {
                font-size: 16px;
                font-weight: 600;
                line-height: 36px;
              }
            }

            .porgressBox {
              width: 100%;
              height: 6px;
              background: rgba(255, 255, 255, 0.13);
              display: flex;
              flex-direction: row;

              .progressPer {
                width: 80%;
                height: 6px;
                background: linear-gradient(271deg, #29C6FA 1%, rgba(27, 126, 242, 0.49) 99%);
              }

              .progressAct {
                width: 2px;
                height: 8px;
                background: #FFFFFF;
                border-radius: 134px;
                position: relative;
                top: -1px
              }
            }
          }
        }

        .list1 {
          background: rgba(8, 107, 215, 0.05);
          width: 100%;
          line-height: 24px;
          font-size: 16px;

          .list1Warp {
            width: 100%;
            // height: 136px;
            height: calc(29vh - 135px);
            margin: 0 auto;
            overflow: hidden;
          }

          .item.tab {
            font-weight: bold;
            color: #29F1FA;
          }

          .item {
            width: 100%;
            display: flex;
            flex-direction: row;
            flex-wrap: nowrap;
            justify-content: space-around;
            color: #fff;
            text-align: center;

            p:nth-child(1) {
              width: calc(50% - 55px);
            }

            p:nth-child(2) {
              width: calc(50% - 55px);
            }

            p:nth-child(3) {
              width: 66px;
            }

            p:last-child {
              width: 20px;
            }
          }

          .item:hover {
            background-color: #1D4D96;
          }
        }
      }
    }
  }

  .main {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
  }

  .statistics {
    width: 1084px;
    position: absolute;
    top: 103px;
    right: calc(50% - 542px);
    z-index: 999;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-around;
    background: linear-gradient(180deg, #131B2E 0%, #0A3A76 100%);
    box-sizing: border-box;
    border: 1px solid;
    border-image: linear-gradient(180deg, rgba(255, 255, 255, 0.06) 4%, rgba(255, 255, 255, 0.85) 100%) 1;
    padding: 20px 8px;

    .item {
      display: flex;
      flex-direction: row;
      flex-wrap: nowrap;
      justify-content: space-around;
      align-items: center;
      align-self: center;
      align-content: center;

      .thumb {
        width: 50px;
        margin-right: 12px;

        img {
          width: 100%;
        }
      }

      .info {
        white-space: nowrap;

        p {
          padding: 0;
          margin: 0;
        }

        .name {
          font-size: 16px;
          color: rgba(255, 255, 255, 0.64);
        }

        .num {
          font-size: 24px;
          font-weight: bold;
          color: rgba(255, 255, 255, 0.87);
        }

        span.unit {
          font-size: 16px;
          color: rgba(255, 255, 255, 0.64);
          margin-left: 3px;
        }
      }

      .divide {
        margin-left: 10px;

        img {
          height: 43px;
        }
      }
    }
  }

  .tipsLabel {
    position: absolute;
    top: 245px;
    left: calc(50% - 521px);
    z-index: 999;

    .item {
      font-size: 16px;
      line-height: 20px;
      color: #fff;
      display: flex;
      flex-direction: row;
      align-items: center;
      align-self: center;
      align-content: center;
      margin-bottom: 5px;

      img {
        width: 18px;
        margin-right: 5px;
      }
    }
  }

  .videoBox {
    width: 1084px;
    position: absolute;
    bottom: 35px;
    right: calc(50% - 542px);
    z-index: 999;

    .title {
      width: 100%;
      height: 34px;
      background: url('../../assets/images/index/left_arr.png') no-repeat;
      background-size: 7px 13px;
      background-position: left center;
      font-size: 20px;
      line-height: 34px;
      padding-left: 15px;
      color: rgba(255, 255, 255, 0.87);
      margin-bottom: 10px;
      display: flex;
      flex-direction: row;
      justify-content: space-between;

      .tab {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        align-self: center;
        align-content: center;
        width: 80px;
        height: 32px;
        border-radius: 2px;
        padding: 2px;
        box-sizing: border-box;
        background: rgba(255, 255, 255, 0.85);
        margin-right: 15px;

        .tabItem {
          width: 38px;
          height: 28px;
          font-size: 12px;
          line-height: 28px;
          text-align: center;
          color: #0C65CE;
          cursor: pointer;
        }

        .tabItem:hover {
          border-radius: 1px;
          background: #0C65CE;
          color: #fff;
        }
      }
    }

    .content {
      display: flex;
      flex-direction: row;
      justify-content: space-between;

      .item {
        position: relative;

        span {
          display: inline-block;
          border-radius: 2px;
          opacity: 1;
          background: rgba(27, 126, 242, 0.28);
          position: absolute;
          top: 5px;
          left: 5px;
          font-size: 16px;
          font-weight: 600;
          line-height: 24px;
          color: #FFFFFF;
          padding: 4px 5px;
        }

        img {
          width: 334px;
          cursor: pointer;
        }

        img.svg {
          width: 86px;
          position: absolute;
          top: 30px;
          left: calc(50% - 43px);
        }
      }
    }
  }

  .bottom {
    position: absolute;
    bottom: 0;
    width: 100%;
    text-align: center;
    z-index: 999;
  }

  .layerInfo {
    position: absolute;
    top: 300px;
    right: calc(50% - 200px);
    width: 243px;
    height: 301.12px;
    z-index: 999;
    background: url('../../assets/images/index/layer.png') no-repeat;
    background-size: cover;
    padding: 23px 15px;
    box-sizing: border-box;

    .list {
      width: 100%;
      height: 240px;
      overflow-y: auto;

      .item {
        width: 100%;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        border-bottom: 1px dashed rgba(26, 255, 241, 0.12);
        padding-bottom: 12px;
        margin-bottom: 12px;

        .content {
          .title {
            font-size: 16px;
            font-weight: 600;
            line-height: 18px;
            color: #09D4DE;
            margin-bottom: 8px;
          }

          .des {
            font-size: 13px;
            line-height: 18px;
            color: rgba(255, 255, 255, 0.64);
            margin-bottom: 4px;
          }
        }

        .more {
          cursor: pointer;
        }
      }

      .item:last-child {
        border: none;
      }
    }
  }

  .layerBox {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    background: rgba(0, 10, 30, 0.4);
    z-index: 999;

    .showlayer {
      width: 1090px;
      height: 612.88px;
      margin: calc(50vh - 306px) auto;
      background: url('../../assets/images/index/layer1.png') no-repeat;
      background-size: cover;

      .title {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        align-self: center;
        align-content: center;
        height: 62px;
        padding: 0 34px;
        box-sizing: border-box;

        .info {
          font-size: 24px;
          font-weight: 600;
          color: #00FFF0;
          display: flex;
          flex-direction: row;
          align-items: center;
          align-self: center;
          align-content: center;

          img {
            width: 24px;
            margin-right: 5px;
          }
        }

        .closed {
          width: 24px;
          cursor: pointer;

          img {
            width: 24px;
          }
        }
      }

      .content {
        width: 100%;

        #dplayer {
          width: 1026px;
          height: 482px;
          margin: 33px auto;
        }
      }
    }
  }
}

::-webkit-scrollbar {
  height: 9px !important;
  width: 9px !important;
}

::-webkit-scrollbar-thumb {
  border-radius: 0;
  border-style: dashed;
  background-color: rgba(157, 165, 183, 0.4);
  border-color: transparent;
  border-width: 1.5px;
  background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(157, 165, 183, 0.7)
}

.mr5 {
  margin-right: 5px;
}

// 地图弹窗插件样式
.returns {
  color: #fff;
  font-size: 0.8vw;
  position: absolute;
  top: 245px;
  left: calc(50% - 521px);
  letter-spacing: 0.1vw;
  text-align: center;
  padding: 4px 7px;
  cursor: pointer;
  border: 1px solid #0C65CE;
  z-index: 999;
}

.returns:hover {
  opacity: 0.7;
}

.rightButton {
  display: none;
  position: absolute;
  right: 23vw;
  bottom: 3vh;
  width: 4vw;

  .common {
    width: 100%;
    height: 3vh;
    border: 1px solid #00ffff;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 1.2vh 0;
    color: #fafafa;
    opacity: 0.5;
    font-size: 0.7vw;
    cursor: pointer;
    transition: 1s;
  }

  .selected {
    opacity: 1 !important;
    transition: 1s;
  }
}

#provinceName {
  pointer-events: none;
  position: absolute;
  left: 0;
  top: 0;
  color: #8ee5ee;
  padding: 10px;
  width: 200px;
  height: 20px;
  line-height: 20px;
  text-align: center;
  font-size: 13px;
}

#cityName {
  pointer-events: none;
  position: absolute;
  left: 0;
  top: 0;
  color: #8ee5ee;
  padding: 10px;
  width: 200px;
  height: 20px;
  line-height: 20px;
  text-align: center;
  font-size: 13px;
}

#prismValue {
  position: absolute;
  top: 0;
  left: 0;
  color: #fafafa;
}

#mapTag {
  z-index: 997;
  position: absolute;
  top: 0;
  left: 0;
  color: #000;
  font-size: 0.6vw;
  width: 4.2vw;
  height: 4.7vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  .content {
    width: 100%;
    height: calc(100% - 1vw);
    background: #0e1937;
    border: 1px solid #6298a9;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fafafa;

    #mapTag_value {
      color: #ffd700;
    }
  }

  .content::before {
    content: "";
    width: 100%;
    height: calc(100% - 1vw);
    position: absolute;
    background: linear-gradient(to top, #26aad1, #26aad1) left top no-repeat,
      //上左
      linear-gradient(to right, #26aad1, #26aad1) left top no-repeat,
      linear-gradient(to top, #26aad1, #26aad1) right bottom no-repeat,
      //下右
      linear-gradient(to left, #26aad1, #26aad1) right bottom no-repeat; //右下
    background-size: 2px 10px, 16px 2px, 2px 10px, 16px 2px;
    pointer-events: none;
  }

  .arrow {
    background: url("../../assets/images/arrow.png") no-repeat;
    background-size: 100% 100%;
    width: 1vw;
    height: 1vw;
  }
}

#popup {
  z-index: 999;
  position: absolute;
  left: 0px;
  top: 0px;
  width: 41.66vw;
  height: 26.59vh;
  display: flex;

  .popup_line {
    margin-top: 4%;
    width: 24%;
    height: 26%;
    background: url("../../assets/images/popup_line.png") no-repeat;
    background-size: 100% 100%;
  }

  .popup_Main {
    width: 35%;
    height: 80%;

    .popupMain_top {
      width: 100%;
      height: 10%;
      background: url("../../assets/images/popupMain_head.png") no-repeat;
      background-size: 100% 100%;
    }

    .popupMain_footer {
      width: 100%;
      height: 10%;
      background: url("../../assets/images/popupMain_footer.png") no-repeat;
      background-size: 100% 100%;
    }

    .popup_content {
      color: #fafafa;
      // background: rgba(47, 53, 121, 0.9);
      background-image: linear-gradient(to bottom, rgba(15, 36, 77, 1), rgba(8, 124, 190, 1));
      border-radius: 10px;
      width: 100%;
      height: 70%;
      padding: 5% 0%;

      .popup_head {
        width: 100%;
        height: 12%;
        margin-bottom: 2%;
        display: flex;
        align-items: center;

        .popup_title {
          color: #8ee5ee;
          font-size: 1vw;
          letter-spacing: 5px;
          width: 88%;
          height: 100%;
          display: flex;
          align-items: center;

          .title_icon {
            width: 0.33vw;
            height: 100%;
            background: #2586ff;
            margin-right: 10%;
          }
        }

        .close {
          cursor: pointer;
          pointer-events: auto;
          width: 1.5vw;
          height: 1.5vw;
          background: url("../../assets/images/close.png") no-repeat;
          background-size: 100% 100%;
        }
      }

      .popup_item {
        display: flex;
        align-items: center;
        width: 85%;
        padding-left: 5%;
        height: 18%;
        // background: rgb(160, 196, 221);
        border-radius: 10px;
        margin: 2.5% 0%;
        margin-left: 10%;

        div {
          line-height: 100%;
          margin-right: 10%;
        }

        .item_value {
          font-size: 0.9vw;
          color: #00ffff;
          font-weight: 600;
          letter-spacing: 2px;
        }
      }
    }
  }
}
</style>
